module exec (
    input   logic   [5:0]   op_code,
    input   logic   [5:0]   func,
    input   logic           zf,

    output  logic   [1:0]   w_r_s,
    output  logic           imm_s,
    output  logic           rt_imm_s,
    output  logic   [1:0]   wr_data_s,
    output  logic   [2:0]   ALU_OP,
    output  logic           Write_Reg,
    output  logic           Mem_Write,
    output  logic   [1:0]   PC_s
);


always_comb begin
    case (op_code)
        6'b000000: begin : R_Type
            w_r_s       = 2'd0;
            imm_s       = 1'b0;
            rt_imm_s    = 1'b0;
            wr_data_s   = 2'd0;
            Write_Reg   = 1'b1;
            Mem_Write   = 1'b0;
            PC_s        = (func == 6'b001000) ?2'd1 :2'd0;
            case (func)
                6'b100000: ALU_OP = 3'b100; // +
                6'b100010: ALU_OP = 3'b101; // -
                6'b100100: ALU_OP = 3'b000; // &
                6'b100101: ALU_OP = 3'b001; // |
                6'b100110: ALU_OP = 3'b010; // ^
                6'b100111: ALU_OP = 3'b011; // ~|
                6'b101011: ALU_OP = 3'b110; // < ?1 :0
                6'b000100: ALU_OP = 3'b111; // <<
                6'b001000: ALU_OP = 3'b100; // jr
                default:   ALU_OP = 3'b000;
            endcase
        end
        6'b001000: begin : addi
            w_r_s       = 2'd1;
            imm_s       = 1'b1;
            rt_imm_s    = 1'b1;
            wr_data_s   = 2'd0;
            ALU_OP      = 3'b100;
            Write_Reg   = 1'b1;
            Mem_Write   = 1'b0;
            PC_s        = 2'd0;
        end
        6'b001100: begin : andi
            w_r_s       = 2'd1;
            imm_s       = 1'b0;
            rt_imm_s    = 1'b1;
            wr_data_s   = 2'd0;
            ALU_OP      = 3'b000;
            Write_Reg   = 1'b1;
            Mem_Write   = 1'b0;
            PC_s        = 2'd0;
        end
        6'b001110: begin : xori
            w_r_s       = 2'd1;
            imm_s       = 1'b0;
            rt_imm_s    = 1'b1;
            wr_data_s   = 2'd0;
            ALU_OP      = 3'b010;
            Write_Reg   = 1'b1;
            Mem_Write   = 1'b0;
            PC_s        = 2'd0;
        end
        6'b001011: begin : sltiu
            w_r_s       = 2'd1;
            imm_s       = 1'b0;
            rt_imm_s    = 1'b1;
            wr_data_s   = 2'd0;
            ALU_OP      = 3'b110;
            Write_Reg   = 1'b1;
            Mem_Write   = 1'b0;
            PC_s        = 2'd0;
        end
        6'b100011: begin : lw
            w_r_s       = 2'd1;
            imm_s       = 1'b1;
            rt_imm_s    = 1'b1;
            wr_data_s   = 2'd1;
            ALU_OP      = 3'b100;
            Write_Reg   = 1'b1;
            Mem_Write   = 1'b0;
            PC_s        = 2'd0;
        end
        6'b101011: begin : sw
            w_r_s       = 2'd0;
            imm_s       = 1'b1;
            rt_imm_s    = 1'b1;
            wr_data_s   = 2'd0;
            ALU_OP      = 3'b100;
            Write_Reg   = 1'b0;
            Mem_Write   = 1'b1;
            PC_s        = 2'd0;
        end
        6'b000100: begin : beq
            w_r_s       = 2'd0;
            imm_s       = 1'b1;
            rt_imm_s    = 1'b0;
            wr_data_s   = 2'd0;
            ALU_OP      = 3'b101;
            Write_Reg   = 1'b0;
            Mem_Write   = 1'b0;
            PC_s        = (zf) ?2'd2 :2'd0;
        end
        6'b000101: begin : bne
            w_r_s       = 2'd0;
            imm_s       = 1'b1;
            rt_imm_s    = 1'b0;
            wr_data_s   = 2'd0;
            ALU_OP      = 3'b101;
            Write_Reg   = 1'b0;
            Mem_Write   = 1'b0;
            PC_s        = (zf) ?2'd0 :2'd2;
        end
        6'b000010: begin : j
            w_r_s       = 2'd0;
            imm_s       = 1'b0;
            rt_imm_s    = 1'b0;
            wr_data_s   = 2'd0;
            ALU_OP      = 3'b000;
            Write_Reg   = 1'b0;
            Mem_Write   = 1'b0;
            PC_s        = 2'd3;
        end
        6'b000011: begin : jal
            w_r_s       = 2'd2;
            imm_s       = 1'b0;
            rt_imm_s    = 1'b0;
            wr_data_s   = 2'd2;
            ALU_OP      = 3'b000;
            Write_Reg   = 1'b1;
            Mem_Write   = 1'b0;
            PC_s        = 2'd3;
        end
        default: begin
            w_r_s       = 2'd0;
            imm_s       = 1'b0;
            rt_imm_s    = 1'b0;
            wr_data_s   = 2'd0;
            ALU_OP      = 3'b000;
            Write_Reg   = 1'b0;
            Mem_Write   = 1'b0;
            PC_s        = 2'd0;
        end
    endcase
end


endmodule
